//--------------------------------- PACKAGE ------------------------------------
package com.wuneng.commonlibrary.hardware.nfc;

//--------------------------------- IMPORTS ------------------------------------

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.nfc.tech.MifareClassic;
import android.os.Build;
import android.util.Log;

import java.io.IOException;


//[------------------------------ MAIN CLASS ----------------------------------]
@TargetApi(Build.VERSION_CODES.GINGERBREAD_MR1)

/**
* This class stands for mifare class card.
*/
@SuppressLint("NewApi")
public class MifareClassCard {
	
	/**
	 * Constructor.
	 * @param sectorSize size of the sectors.
	 */
	public MifareClassCard(int sectorSize){
		sectors=new MifareSector[sectorSize];
		SECTORCOUNT=sectorSize;
		initializeCard();
	}
	/**
	 * initial card 
	 */
	public void initializeCard(){
		for(int i=0;i<SECTORCOUNT;i++){
			sectors[i]=new MifareSector();
			sectors[i].sectorIndex=i;
			sectors[i].keyA=new MifareKey();
			sectors[i].keyB=new MifareKey();
			for(int j=0;j<4;j++){
				sectors[i].blocks[j]=new MifareBlock();
				sectors[i].blocks[j].blockIndex=i*4+j;
			}
		}
	}
	
	
	/**
	 * get sector at given index.
	 * @param index the index of the sector.
	 * @return the sector at given index;
	 */
	public MifareSector getSector(int index){
		if(index>=SECTORCOUNT){
			throw new IllegalArgumentException("Invaid index for sector"); 
		}
		return sectors[index];
	}
	
	
	
	/**
	* set sector at given index.
	* @param index the index of the sector.
	*/
	public void setSector(int index, MifareSector sector) {
		if (index >= SECTORCOUNT) {
			throw new IllegalArgumentException("Invaid index for sector");
		}
		sectors[index]=sector;
	}
	
	
	/**
	 * get the count of the sector.
	 * @return the count of the sector.
	 */
	public int getSectorCount(){
		return SECTORCOUNT;
		
	}
	
	
	/**
	 * set the new sector count
	 * @param newCount net sector count
	 */
	public void setSectorCount(int newCount){
		if(SECTORCOUNT<newCount){
			sectors=new MifareSector[newCount];
			initializeCard();
		}
		SECTORCOUNT=newCount;
		
	}

	/**
	 * debug print information.
	 */
	public void debugPrint() {
		int blockIndex=0;
		for (int i = 0; i < SECTORCOUNT; i++) {
			MifareSector sector = sectors[i];
			
			if (sector != null) {
				Log.i(TAG, "Sector " + i);
				for (int j = 0; j < MifareSector.BLOCKCOUNT; j++) {
					MifareBlock block = sector.blocks[j];
					if(block!=null){
						byte[] raw = block.getData();
						String hexString = "  Block "+ j +" "
								+Converter.getHexString(raw, raw.length)
								+"  ("+blockIndex+")";
						Log.i(TAG, hexString);
					}
					blockIndex++;

				}
			}
		}
	}
	
	public String GetCardId()
	{
	    String result ="";
	    int blockIndex=0;
		for (int i = 0; i < SECTORCOUNT; i++) {
			MifareSector sector = sectors[i];
			
			if (sector != null) {
				Log.i(TAG, "Sector " + i);
				for (int j = 0; j < MifareSector.BLOCKCOUNT; j++) {
					MifareBlock block = sector.blocks[j];
					if(block!=null){
						byte[] raw = block.getData();
						String hexString = "  Block "+ j +" "
								+Converter.getHexString(raw, raw.length)
								+"  ("+blockIndex+")";
						Log.i(TAG, hexString);
						if(i==0&&j==0)
						{
						    result = Converter.getHexString(raw, 4);
						    Log.i(TAG, result);
						}
					}
					blockIndex++;
				}
			}
		}
		return result;
	}
	
	public String GetUID(MifareClassic mfc,MifareClassCard mifareClassCard)
	{
		String result ="";
		
		try {
			GetData(0,0,mfc,mifareClassCard);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return result;
		}
		
		MifareSector sector = sectors[0];
			
		if (sector != null) {
			MifareBlock block = sector.blocks[0];
			if(block!=null){
			byte[] raw = block.getData();
								
		    result = Converter.getHexString(raw, 4);
		    Log.i(TAG, result);
			}
		}
		return result;
	}
	
	@SuppressLint("NewApi")
	public String getCardType(MifareClassic mfc)
	{
		String typeS="";
		int type = mfc.getType();//获取TAG的类型              
		               
		switch (type) {               
		case MifareClassic.TYPE_CLASSIC:                  
			typeS = "TYPE_CLASSIC";                  
			break;               
			case MifareClassic.TYPE_PLUS:                   
				typeS = "TYPE_PLUS";                   
				break;               
			case MifareClassic.TYPE_PRO:                  
				typeS = "TYPE_PRO";                   
				break;               
			case MifareClassic.TYPE_UNKNOWN:                  
				typeS = "TYPE_UNKNOWN";                   
				break; 
		}
		return typeS;
	}
	
	@TargetApi(Build.VERSION_CODES.GINGERBREAD_MR1)
	@SuppressLint("NewApi")
	public String GetData(int sector,int block,MifareClassic mfc,MifareClassCard mifareClassCard) throws IOException
	{
		String result="";
		
		boolean auth=false;
		MifareSector mifareSector = new MifareSector();
		mifareSector.sectorIndex = sector;
		// 6.1) authenticate the sector
		auth = mfc.authenticateSectorWithKeyA(sector,
				MifareClassic.KEY_DEFAULT);//验证密码
		mifareSector.authorized = auth;
		if (auth) {
			// 6.2) In each sector - get the block count
			int bCount = mfc.getBlockCountInSector(sector);
			bCount = Math.min(bCount, MifareSector.BLOCKCOUNT);
			int bIndex = mfc.sectorToBlock(sector);
			
			byte[] data = mfc.readBlock(bIndex);
			MifareBlock mifareBlock = new MifareBlock(data);
			mifareBlock.blockIndex = bIndex;
			mifareSector.blocks[block] = mifareBlock;
			
			mifareClassCard.setSector(mifareSector.sectorIndex,
					mifareSector);
			
			byte[] raw = mifareClassCard.getSector(sector).blocks[block].getData();
			return result = Converter.getHexString(raw, 16);

		} else { // Authentication failed - Handle it
			return "";
		}

	}
	
	/**
	 * the size of the sector.
	 */
	private int SECTORCOUNT=16;
	
	/**
	 * Log TAG.
	 */
	protected String TAG="MifareCardInfo";
	
	/**
	 * sectors.
	 */
	private MifareSector[] sectors;
}
